import { AxiosRequestConfig, AxiosResponse } from './types'
import qs from 'qs'
import parseHeaders from 'parse-headers'
export default class Axios {
  request<T>(config: AxiosRequestConfig): Promise<AxiosResponse<T>> {
    return this.dispatchRequst<T>(config)
  }
  dispatchRequst<T>(config: AxiosRequestConfig): Promise<AxiosResponse<T>> {
    return new Promise<AxiosResponse<T>>(function (resolve, reject) {
      let { method, url, params, data, headers, timeout } = config
      let xhr: XMLHttpRequest = new XMLHttpRequest()
      if (params && typeof params === 'object') {
        params = qs.stringify(params)
      }
      if (params) {
        url += ((url!.indexOf('?') > -1 ? '&' : '?') + params)
      }
      xhr.open(method!, url!, true)


      xhr.responseType = 'json'
      xhr.onreadystatechange = function () {
        const { readyState, status, statusText } = xhr
        if (readyState === 4 && status !== 0) {
          if (status >= 200 && status < 300) {
            let params: AxiosResponse<T> = {
              data: xhr.response ? xhr.response : xhr.responseText,
              status: status,
              statusText: statusText,
              headers: parseHeaders(xhr.getAllResponseHeaders()),
              request: xhr,
              config
            }
            resolve(params)
          } else {
            reject(`Error: Request failed with status code ${status}`)
          }
        }
      }

      if (headers) {
        for (let key in headers) {
          xhr.setRequestHeader(key, headers[key])
        }
      }
      let body: string | null = null
      if (data) {
        body = JSON.stringify(data)
      }

      xhr.onerror = function () {
        reject('net::ERR_INTERNET_DISCONNECTED')
      }
      if (timeout) {
        xhr.timeout = timeout
        xhr.ontimeout = function () {
          reject(`Error: timeout of ${timeout}ms exceeded`)
        }
      }
      xhr.send(body)
    })
  }
}